//===============================================================================
// Microsoft Architecture Strategy Team
// LitwareHR - SaaS Sample Application
//===============================================================================
// Copyright  Microsoft Corporation.  All rights reserved.
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY
// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT
// LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE.
//===============================================================================
// The example companies, organizations, products, domain names,
// e-mail addresses, logos, people, places, and events depicted
// herein are fictitious.  No association with any real company,
// organization, product, domain name, email address, logo, person,
// places, or events is intended or should be inferred.
//===============================================================================


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using LitwareHR.Recruiting.DataModel.Sitka.Tests.Mocks;
using LitwareHR.Recruiting.Contract;
using Shp.Runtime.Sitka.ServiceAgent.Entities;
using Shp.Runtime.Sitka.ServiceAgent;
using System.Collections.ObjectModel;
using Shp.Runtime.Contract;
using Shp.Runtime.Sitka.ServiceAgent.Managers;

namespace LitwareHR.Recruiting.DataModel.Sitka.Tests
{

    [TestClass]
    public class RecruitingDataModelFixture
    {
        private Guid tenantId;
        private TestableRepositoryFactory factory;
        private DataInitialize dataInitialize;

        [TestInitialize]
        public void Initialize()
        {
            tenantId = Guid.NewGuid();
            factory = new TestableRepositoryFactory(tenantId);
            factory.CreateTenantContainer();

            dataInitialize = new DataInitialize(tenantId.ToString(), factory.MetadataContainerName);
        }

        [TestCleanup]
        public void CleanUp()
        {
            factory.DeleteTenantContainer();
        }

        [TestMethod]
        public void ShouldGetResume()
        {
            Guid id = Guid.NewGuid();
            string additionalInfo = "additionalInfo1", address="address1", applicantName="applicantName1", applicantSurname="applicantSurname1", phoneNumber="phoneNumber1";
            DateTime date = DateTime.Now;

            dataInitialize.CreateResumeInstance(id, additionalInfo, address, applicantName, applicantSurname, phoneNumber, date, Guid.NewGuid(), "user@domain", true, false);

            RecruitingDataModel recruitingServices = new RecruitingDataModel(factory);
            Resume resume = recruitingServices.GetResume(id, tenantId);
            Assert.IsNotNull(resume);
            Assert.AreEqual(additionalInfo, resume.AdditionalInfo);
            Assert.AreEqual(address, resume.Address);
            Assert.AreEqual(applicantName, resume.ApplicantName);
            Assert.AreEqual(applicantSurname, resume.ApplicantLastName);
            Assert.AreEqual(phoneNumber, resume.PhoneNumber);
            Assert.AreEqual(date.ToString(), resume.Date.ToString());
            Assert.AreEqual("user@domain", resume.Upn.ToString());
        }

        [TestMethod]
        public void ShouldSubmitResume()
        {
            Resume resume = new Resume();
            resume.Id = Guid.NewGuid();
            resume.AdditionalInfo = "additionalInfo1";
            resume.Address = "address1";
            resume.ApplicantName = "applicantName1";
            resume.ApplicantLastName = "applicantSurname1";
            resume.PhoneNumber = "phoneNumber1";
            resume.Date = DateTime.Now;            

            resume.PositionId = Guid.NewGuid();
            resume.Upn = new Shp.Runtime.Contract.Upn("user@test");
            resume.IsVideoAvailable = false;
            resume.IsVideoUploaded = false;

            RecruitingDataModel recruitingServices = new RecruitingDataModel(factory);
            recruitingServices.SubmitResume(resume, tenantId);

            Resume resumeRetrieved = recruitingServices.GetResume(resume.Id, tenantId);
            Assert.IsNotNull(resumeRetrieved);
            Assert.AreEqual(resume.AdditionalInfo, resumeRetrieved.AdditionalInfo);
            Assert.AreEqual(resume.Address, resumeRetrieved.Address);
            Assert.AreEqual(resume.ApplicantName, resumeRetrieved.ApplicantName);
            Assert.AreEqual(resume.ApplicantLastName, resumeRetrieved.ApplicantLastName);
            Assert.AreEqual(resume.PhoneNumber, resumeRetrieved.PhoneNumber);
            Assert.AreEqual(resume.Date.ToShortDateString(), resumeRetrieved.Date.ToShortDateString());
            Assert.AreEqual(resume.Upn.ToString(), resumeRetrieved.Upn.ToString());
            Assert.AreEqual(resume.IsVideoAvailable, resumeRetrieved.IsVideoAvailable);
        }

        [TestMethod]
        public void ShouldSubmitCustomsFieldsResume()
        {
            Resume resume = new Resume();
            resume.Id = Guid.NewGuid();
            resume.AdditionalInfo = "additionalInfo1";
            resume.Address = "address1";
            resume.ApplicantName = "applicantName1";
            resume.ApplicantLastName = "applicantSurname1";
            resume.PhoneNumber = "phoneNumber1";
            resume.Date = DateTime.Now;
            resume.PositionId = Guid.NewGuid();
            resume.Upn = new Shp.Runtime.Contract.Upn("user@test");
            resume.IsVideoAvailable = false;
            resume.IsVideoUploaded = false;

            resume.Fields.Add(new LitwareHR.Recruiting.Contract.Field("mockField", "mockFieldValue"));

            RecruitingDataModel recruitingServices = new RecruitingDataModel(factory);
            recruitingServices.SubmitResume(resume, tenantId);

            using (Repository<GenericExtensibleEntity> repository = factory.GetDataRepository(tenantId))
            {
                GenericExtensibleEntity resumeRetrieved = repository.GetById(resume.Id);
                Assert.IsNotNull(resumeRetrieved);
                Assert.AreEqual(resume.AdditionalInfo, resumeRetrieved.GetFieldValue("AdditionalInfo"));
                Assert.AreEqual(resume.Address, resumeRetrieved.GetFieldValue("Address"));
                Assert.AreEqual(resume.ApplicantName, resumeRetrieved.GetFieldValue("ApplicantName"));
                Assert.AreEqual(resume.ApplicantLastName, resumeRetrieved.GetFieldValue("ApplicantSurname"));
                Assert.AreEqual(resume.PhoneNumber, resumeRetrieved.GetFieldValue("PhoneNumber"));
                Assert.AreEqual(resume.Upn.ToString(), resumeRetrieved.GetFieldValue("Upn"));
                Assert.AreEqual(resume.IsVideoAvailable, bool.Parse(resumeRetrieved.GetFieldValue("IsVideoAvailable")));

                Assert.IsNotNull(resumeRetrieved.GetFieldValue("mockField"));
                Assert.AreEqual("mockFieldValue", resumeRetrieved.GetFieldValue("mockField"));
            }
        }

        [TestMethod]
        public void ShouldAddVideoResume()
        {
            Resume resume = new Resume();
            resume.Id = Guid.NewGuid();
            resume.PositionId = Guid.NewGuid();
            resume.AdditionalInfo = "additionalInfo1";
            resume.Address = "address1";
            resume.ApplicantName = "applicantName1";
            resume.ApplicantLastName = "applicantSurname1";
            resume.PhoneNumber = "phoneNumber1";
            resume.Upn = new Shp.Runtime.Contract.Upn("user@test");
            resume.Date = DateTime.Now;
            resume.IsVideoAvailable = false;
            resume.IsVideoUploaded = false;

            RecruitingDataModel recruitingServices = new RecruitingDataModel(factory);
            recruitingServices.SubmitResume(resume, tenantId);

            recruitingServices.AddVideoResume(resume, tenantId);

            Resume resumeRetrieved = recruitingServices.GetResume(resume.Id, tenantId);

            Assert.IsNotNull(resumeRetrieved);
            Assert.AreEqual(resume.AdditionalInfo, resumeRetrieved.AdditionalInfo);
            Assert.AreEqual(resume.Address, resumeRetrieved.Address);
            Assert.AreEqual(resume.ApplicantName, resumeRetrieved.ApplicantName);
            Assert.AreEqual(resume.ApplicantLastName, resumeRetrieved.ApplicantLastName);
            Assert.AreEqual(resume.PhoneNumber, resumeRetrieved.PhoneNumber);
            Assert.AreEqual(resume.Upn.ToString(), resumeRetrieved.Upn.ToString());
            Assert.AreEqual(true, resumeRetrieved.IsVideoAvailable);
        }

        [TestMethod]
        public void ShouldSetErrorOnVideoResume()
        {
            Resume resume = new Resume();
            resume.Id = Guid.NewGuid();
            resume.PositionId = Guid.NewGuid();
            resume.AdditionalInfo = "additionalInfo1";
            resume.Address = "address1";
            resume.ApplicantName = "applicantName1";
            resume.ApplicantLastName = "applicantSurname1";
            resume.PhoneNumber = "phoneNumber1";
            resume.Date = DateTime.Now;
            resume.Upn = new Shp.Runtime.Contract.Upn("user@test");
            resume.IsVideoAvailable = true;
            resume.IsVideoUploaded = false;

            RecruitingDataModel recruitingServices = new RecruitingDataModel(factory);
            recruitingServices.SubmitResume(resume, tenantId);

            recruitingServices.SetErrorOnVideoResume(resume, tenantId);

            Resume resumeRetrieved = recruitingServices.GetResume(resume.Id, tenantId);

            Assert.IsNotNull(resumeRetrieved);
            Assert.AreEqual(resume.AdditionalInfo, resumeRetrieved.AdditionalInfo);
            Assert.AreEqual(resume.Address, resumeRetrieved.Address);
            Assert.AreEqual(resume.ApplicantName, resumeRetrieved.ApplicantName);
            Assert.AreEqual(resume.ApplicantLastName, resumeRetrieved.ApplicantLastName);
            Assert.AreEqual(resume.PhoneNumber, resumeRetrieved.PhoneNumber);
            Assert.AreEqual(resume.Upn.ToString(), resumeRetrieved.Upn.ToString());
            Assert.AreEqual(false, resumeRetrieved.IsVideoUploaded);
            Assert.AreEqual(true, resumeRetrieved.IsVideoAvailable);
        }

        [TestMethod]
        public void ShouldGetSilverlightAccount()
        {
            Guid tenantId = Guid.NewGuid();
            dataInitialize.AddTenant(tenantId.ToString(), "tenantAlias", "silverligthId", "silverligthKey");

            RecruitingDataModel recruitingServices = new RecruitingDataModel(factory);
            SilverlightAccount account = recruitingServices.GetSilverlightAccount(tenantId);

            Assert.IsNotNull(account);
            Assert.AreEqual("tenantAlias".ToLower(), account.TenantAlias);
            Assert.AreEqual("silverligthId", account.AccountId);
            Assert.AreEqual("silverligthKey", account.AccountKey);
        }

        [TestMethod]
        public void ShouldGetSilverlightAccountNull()
        {
            Guid tenantId = Guid.NewGuid();
            dataInitialize.AddTenant(tenantId.ToString(), "tenantAlias", null, null);

            RecruitingDataModel recruitingServices = new RecruitingDataModel(factory);
            SilverlightAccount account = recruitingServices.GetSilverlightAccount(tenantId);

            Assert.IsNull(account);            
        }

        [TestMethod]
        public void ShouldGetCustomFieldsResume()
        {
            Guid id = Guid.NewGuid();
            string additionalInfo = "additionalInfo1", address = "address1", applicantName = "applicantName1", applicantSurname = "applicantSurname1", phoneNumber = "phoneNumber1";
            DateTime date = DateTime.Now;
            Collection<LitwareHR.Recruiting.Contract.Field> fields = new Collection<LitwareHR.Recruiting.Contract.Field>();
            fields.Add(new LitwareHR.Recruiting.Contract.Field("mockField","mockFieldValue"));
            dataInitialize.CreateResumeInstance(id, additionalInfo, address, applicantName, applicantSurname, phoneNumber, date, Guid.NewGuid(), "user@domain", true, false, fields);
            Guid positionId=Guid.NewGuid();
            dataInitialize.CreateEntityDef(positionId, "position");
            dataInitialize.AddEntityDefField(tenantId, positionId, "mockField", true);

            RecruitingDataModel recruitingServices = new RecruitingDataModel(factory);
            Resume resume = recruitingServices.GetResume(id, tenantId);
            Assert.IsNotNull(resume);
            Assert.AreEqual(additionalInfo, resume.AdditionalInfo);
            Assert.AreEqual(address, resume.Address);
            Assert.AreEqual(applicantName, resume.ApplicantName);
            Assert.AreEqual(applicantSurname, resume.ApplicantLastName);
            Assert.AreEqual(phoneNumber, resume.PhoneNumber);
            Assert.AreEqual(date.ToString(), resume.Date.ToString());
            Assert.AreEqual("user@domain", resume.Upn.ToString());
            Assert.AreEqual(1, resume.Fields.Count);
            Assert.AreEqual("mockField", resume.Fields.First().Name);
            Assert.AreEqual("mockFieldValue", resume.Fields.First().Value);
        }

        [TestMethod]        
        public void ShouldSearchResumes()
        {
            DateTime date = new DateTime(2008, 1, 1);
            string   applicantName = "applicantName1", applicantSurname = "applicantSurname1", phoneNumber = "phoneNumber1";            

            Collection<LitwareHR.Recruiting.Contract.Field> fields = new Collection<LitwareHR.Recruiting.Contract.Field>();
            fields.Add(new LitwareHR.Recruiting.Contract.Field("mockField", "mockFieldValue"));
                        
            dataInitialize.CreateResumeInstance(Guid.NewGuid(), "additionalInfo1", "address1", applicantName, applicantSurname, phoneNumber, DateTime.Now, Guid.NewGuid(), "user@domain", true, false, fields);
            dataInitialize.CreateResumeInstance(Guid.NewGuid(), "additionalInfo1", "address1", applicantName, applicantSurname, phoneNumber, date, Guid.NewGuid(), "user@domain", true, false, fields);
            dataInitialize.CreateResumeInstance(Guid.NewGuid(), "additionalInfo1", "ffff", applicantName, applicantSurname, phoneNumber, DateTime.Now, Guid.NewGuid(), "user@domain", true, false, fields);
            dataInitialize.CreateResumeInstance(Guid.NewGuid(), "additionalInfo1", "address1", applicantName, applicantSurname, phoneNumber, DateTime.Now, Guid.NewGuid(), "user@domain", true, false, fields);

            Guid positionId = Guid.NewGuid();
            dataInitialize.CreateEntityDef(positionId, "position");
            dataInitialize.AddEntityDefField(tenantId, positionId, "mockField", true);

            List<PropertyFilter> filters = new List<PropertyFilter>();
            
            PropertyFilter filter = new PropertyFilter("Address", PropertyType.String, LogicalOperator.Equal, "address1", LogicalConnector.And);
            List<PropertyFilter> subFilter = new List<PropertyFilter>();
            subFilter.Add(new PropertyFilter("Date", PropertyType.DateTime, LogicalOperator.GreaterOrEqualThan, new DateTime(2008, 2, 12), LogicalConnector.And));
            subFilter.Add(new PropertyFilter("Date", PropertyType.DateTime, LogicalOperator.LessOrEqualThan, new DateTime(2008, 3, 12), LogicalConnector.Or));
            filter.SetSubFilters(subFilter.ToArray(), LogicalConnector.And);

            filters.Add(filter);

            filters.Add(new PropertyFilter("mockField", PropertyType.String, LogicalOperator.Equal, "mockFieldValue", LogicalConnector.And));

            RecruitingDataModel recruitingServices = new RecruitingDataModel(factory);
            Resume[] resumes = recruitingServices.SearchResumes(filters.ToArray(), tenantId);
            Assert.IsNotNull(resumes);
            Assert.AreEqual(2, resumes.Length);
        }

        [TestMethod]        
        public void ShouldCrossTenantSearchResumes()
        {
            //metadata
            Guid positionId = Guid.NewGuid();
            dataInitialize.CreateEntityDef(positionId, "position");
            dataInitialize.AddTenant(tenantId.ToString(), "contoso", Guid.NewGuid().ToString(), Guid.NewGuid().ToString());

            //data tenantid (1) implicit test

            dataInitialize.AddEntityDefField(tenantId, positionId, "mockField", true);

            DateTime date;
            string applicantName = "applicantName1", applicantSurname = "applicantSurname1", phoneNumber = "phoneNumber1";
            Assert.IsTrue(DateTime.TryParse("2008-01-01", out date));

            Collection<LitwareHR.Recruiting.Contract.Field> fields = new Collection<LitwareHR.Recruiting.Contract.Field>();
            fields.Add(new LitwareHR.Recruiting.Contract.Field("mockField", "mockFieldValue"));

            dataInitialize.CreateResumeInstance(Guid.NewGuid(), "additionalInfo1", "address1", applicantName, applicantSurname, phoneNumber, DateTime.Now, Guid.NewGuid(), "user@domain", true, false, fields);
            dataInitialize.CreateResumeInstance(Guid.NewGuid(), "additionalInfo1", "address1", applicantName, applicantSurname, phoneNumber, date, Guid.NewGuid(), "user@domain", true, false, fields);
            dataInitialize.CreateResumeInstance(Guid.NewGuid(), "additionalInfo1", "ffff", applicantName, applicantSurname, phoneNumber, DateTime.Now, Guid.NewGuid(), "user@domain", true, false, fields);
            dataInitialize.CreateResumeInstance(Guid.NewGuid(), "additionalInfo1", "address1", applicantName, applicantSurname, phoneNumber, DateTime.Now, Guid.NewGuid(), "user@domain", true, false, fields);

            //data tenantid (1) implicit test                      
            Guid tenantId2 = Guid.NewGuid();
            dataInitialize.AddTenant(tenantId2.ToString(), "fabrikam", Guid.NewGuid().ToString(), Guid.NewGuid().ToString());

            dataInitialize.AddEntityDefField(tenantId2, positionId, "mockField", true);

            ContainerManager.CreateContainer(tenantId2.ToString());
            dataInitialize.Container = tenantId2.ToString();

            dataInitialize.CreateResumeInstance(Guid.NewGuid(), "additionalInfo1", "fraca", applicantName, applicantSurname, phoneNumber, DateTime.Now, Guid.NewGuid(), "user@domain", true, false, fields);
            dataInitialize.CreateResumeInstance(Guid.NewGuid(), "additionalInfo1", "address1", applicantName, applicantSurname, phoneNumber, date, Guid.NewGuid(), "user@domain", true, false, fields);            
            dataInitialize.CreateResumeInstance(Guid.NewGuid(), "additionalInfo1", "address1", applicantName, applicantSurname, phoneNumber, date, Guid.NewGuid(), "user@domain", true, false, fields);


            //Create Filter
            List<PropertyFilter> filters = new List<PropertyFilter>();

            PropertyFilter filter = new PropertyFilter("Address", PropertyType.String, LogicalOperator.Equal, "address1", LogicalConnector.And);
            List<PropertyFilter> subFilter = new List<PropertyFilter>();
            subFilter.Add(new PropertyFilter("mockField", PropertyType.String, LogicalOperator.Equal, "mockFieldValue", LogicalConnector.Or));            
            filter.SetSubFilters(subFilter.ToArray(), LogicalConnector.And);

            filters.Add(filter);
           
            RecruitingDataModel recruitingServices = new RecruitingDataModel(factory);
            Resume[] resumes = recruitingServices.SearchCrossTenantResumes(filters.ToArray(), Guid.NewGuid());
            Assert.IsNotNull(resumes);
            Assert.AreEqual(3, resumes.Length);
        }

        [TestMethod]
        public void ShouldGetSitkaQuery()
        {
            List<PropertyFilter> filters = new List<PropertyFilter>();
            filters.Add(new PropertyFilter("s1", PropertyType.String, LogicalOperator.Equal, "s1", LogicalConnector.Or));
            filters.Add(new PropertyFilter("s2", PropertyType.String, LogicalOperator.GreaterOrEqualThan, "s2", LogicalConnector.Or));
            filters.Add(new PropertyFilter("s3", PropertyType.String, LogicalOperator.GreaterThan, "s3", LogicalConnector.Or));
            filters.Add(new PropertyFilter("s4", PropertyType.String, LogicalOperator.LessOrEqualThan, "s4", LogicalConnector.Or));
            filters.Add(new PropertyFilter("s5", PropertyType.String, LogicalOperator.LessThan, "s5", LogicalConnector.Or));
            filters.Add(new PropertyFilter("s6", PropertyType.String, LogicalOperator.NotEqual, "s6", LogicalConnector.Or));
            filters.Add(new PropertyFilter("b1", PropertyType.Boolean, LogicalOperator.Equal, true, LogicalConnector.Or));
            filters.Add(new PropertyFilter("b2", PropertyType.Boolean, LogicalOperator.Equal, false, LogicalConnector.Or));

            string where = SitkaQueryBuilder.GetSitkaQuery(filters.ToArray(), "Resume");            

            string spectedWhere = @"where e.Kind==""Resume"" &&  e[""s1""]==""s1"" || e[""s2""]>=""s2"" || e[""s3""]>""s3"" || e[""s4""]<=""s4"" || e[""s5""]<""s5"" || e[""s6""]!=""s6"" || e[""b1""]==True || e[""b2""]==False ";
            Assert.AreEqual(spectedWhere, where);
        }
    }
}
